<?php

//  Copyright 2010 Ameoto Systems. All Rights Resurved.
//  Written by TheTooth, thetooth@ameoto.com

class Parser {
	var $code = "";
	var $cache = "";
	var $varArray = array(
		"connection" => array(
			"kbytes-per-second" => null
		),
		"server" => array(
			"port" => 80,
			"bind" => "127.0.0.1",
			"use-ipv6" => null,
			"username" => null,
			"groupname" => null,
			"tag" => null,
			"name" => null,
			"modules" => null,
			"document-root" => null,
			"chroot" => null,
			"core-files" => null,
			"dir-listing" => null,
			"errorfile-prefix" => null,
			"error-handler-404" => null,
			"errorlog" => null,
			"follow-symlink" => null,
			"kbytes-per-second" => null,
			"max-connections" => null,
			"max-fds" => null,
			"max-keep-alive-idle" => null,
			"max-keep-alive-requests" => null,
			"max-read-idle" => null,
			"max-request-size" => null,
			"max-worker" => null,
			"max-write-idle" => null,
			"network-backend" => null,
			"pid-file" => null,
			"protocol-http11" => null,
			"range-requests" => null,
			"reject-expect-100-with-417" => null,
			"stat-cache-engine" => null,
			"upload-dirs" => null
		),
		"static-file" => array(
			"etags" => null,
			"exclude-extensions" => null
		),
		"ssl" => array(
			"engine" => null,
			"pemfile" => null,
			"ca-file" => null,
			"use-sslv2" => null,
			"cipher-list" => null,
			"verifyclient" => array(
				"activate" => null,
				"enforce" => null,
				"depth" => null,
				"exportcert" => null,
				"username" => null
			)
		),
		"url" => array(
			"access-deny" => null
		),
		"index-file" => array(
			"names" => null
		),
		"proxy" => array(
			"server" => array(null)
		),
		"mimetype" => array(
			"assign" => null,
			"use-xattr" => null
		)
	);
	
	// Array type callback
	private function callbackArray($key, $value){
		var_dump($key);
		var_dump($value);
		if(is_int($value)){
			if(strstr($value, '#')){
				$type = 'false;';
			}else{
				$type = 'true;';
			}
		}else{
			if(!strstr($value, "=>")){
				$type = '\''.$key.'" => "'.$value.'\';';
			}else{
				$type = '"'.$value.'";';
			}
		}
		return $this->cache.'["'.$key.'"] = '.$type."\n";
	}
	
	// Parse arrays
	private function parseArray($tmp, $module, $var){
		$this->cache = '$this->varArray["'.$module.'"]["'.$var.'"]';
		eval('$data = array('.str_replace(array(",)", '""', '('), array(")", '"*"', 'array('), $tmp).");");
		foreach ($data as $key => $value) {
			eval($this->callbackArray($key, $value));
		}
		echo "ok!\n\n";
	}
	
	// Parse vars
	private function varPrase(){
		foreach(array_keys($this->varArray) as $module){
			foreach(array_keys($this->varArray[$module]) as $var){
				// Pre-fetch basic one liners
				$line = null;
				if(preg_match("/\s+".$module."\.".$var.'\s+\=\s+(.[^\(]+)/', $this->code, $tmp)){
					$line = $tmp[1];
				}
				if(preg_match('/^\"(.+?)\"/', $line, $tmp)){ // Is it a string?
					$this->varArray[$module][$var] = (string)trim(str_replace('"', '', $tmp[1]));
				}elseif(preg_match('/^([0-9]+?)[\n\r]/', $line, $tmp)){ // Or is it an integer?
					$this->varArray[$module][$var] = (int)intval($tmp[1]);
				}elseif(preg_match("/[\s+]".$module."\.".$var.'\s+\=\s+\((.+?)\)[\s+]/sm', $this->code, $tmp)){ // Now were in the shit
					$this->parseArray($tmp[1], $module, $var);
				}
			}
		}
	}
	
	// Generate syntax for object types
	private function bluePrint($type, $key, $keyring){
		switch($type){
			case "integer":
				return (string)intval($keyring);
			break;
			case "string":
				if(preg_match("/&/", $keyring)){
					return '"'.str_replace("*", "", $key).'" => "'.str_replace('&', '', trim($keyring)).'"';
				}else{
					return '"'.trim($keyring).'"';
				}
			break;
			case "array":
				$tmp = "";
				for($i = 0; $i < count($key); $i++){
					$tmp .= $this->bluePrint(gettype($keyring[$key[$i]]), $key[$i], $keyring[$key[$i]]).",\n";
				}
				return "(".substr($tmp, 0, strlen($tmp)-2)."\n)";
			break;
			case "boolean":
				if($keyring == true){
					return '"'.trim($key).'"';
				}else{
					return '#"'.trim($key).'"';
				}
			break;
			case "NULL":
				return '""';
				break;
			default:
				throw new Exception('Unknown type conversion, did you specify one?');
		}
	}
	// Load and proccess config file
	public function _read($file){
		if(!file_exists($file)){
			throw new Exception('Could not load configuration file: '.$file);
		}
		$this->code = preg_replace("/[\n\r\s]([\#]+)\s(.[^\n\r]+)[a-zA-Z0-9\)\#][\n\r]/", "\n", file_get_contents($file));
		$this->varPrase();
		return $this->varArray;
	}
	// Write the config file
	public function _write($file){
		$tmp = "# Generated with lightyC Parser, Written by TheTooth, thetooth@ameoto.com\n\n";
		foreach(array_keys($this->varArray) as $module){
			foreach(array_keys($this->varArray[$module]) as $var){
				$disabled = false;
				if(gettype($this->varArray[$module][$var]) == "NULL"){
					$disabled = true;
				}
				$tmp .= ($disabled ? "#" : "").$module.".".$var." = ".$this->bluePrint(gettype($this->varArray[$module][$var]), (gettype($this->varArray[$module][$var]) == 'array' ?
					array_keys($this->varArray[$module][$var]) : $this->varArray[$module][$var]
				), $this->varArray[$module][$var])."\n";
			}
		}
		if(file_put_contents($file, $tmp) === false){
			throw new Exception('Could not write configuration file: '.$file);
		}
		return $tmp;
	}
}

?>